package jp.sourceforge.akjrcp.textinsert;



import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import jp.sourceforge.akjrcp.akj_betas.Akj_betasPlugin;
import jp.sourceforge.akjrcp.akj_betas.Messages;
import jp.sourceforge.akjrcp.commons.ui.AbstractFileDirChoicer.FileStatusChangeEvent;
import jp.sourceforge.akjrcp.commons.ui.AbstractFileDirChoicer.FileStatusChangeListener;
import jp.sourceforge.akjrcp.dropsomething.DirectoryBasedDropSomething;
import jp.sourceforge.akjrcp.dropsomething.DropsomethingTab;
import jp.sourceforge.akjrcp.dropsomething.IDropSomething;
import jp.sourceforge.akjrcp.potrace.PotraceTabBuilder.PotraceConvertTab;
import jp.sourceforge.akjrcp.ui.FileOverwriteControler;
import jp.sourceforge.akjrcp.ui.FileOverwriteControler.AskOverwrite;
import jp.sourceforge.akjrcp.util.PathnameUtils;
import jp.sourceforge.akjrcp.util.StatusBarUtils;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;

/**
 * This sample class demonstrates how to plug-in a new workbench view. The view
 * shows data obtained from the model. The sample creates a dummy model on the
 * fly, but a real implementation would connect to the model available either in
 * this or another plug-in (e.g. the workspace). The view is connected to the
 * model using a content provider.
 * <p>
 * The view uses a label provider to define how model objects should be
 * presented in the view. Each view can present the same model objects using
 * different labels and icons, if needed. Alternatively, a single label provider
 * can be shared between views in order to ensure that objects of the same type
 * are presented in the same way everywhere.
 * <p>
 */

public class TextInsertTabBuilder  implements IDropSomething{
	public static Log log = LogFactory.getLog(TextInsertTabBuilder.class);
	
	private DropsomethingTab dtab;
	private CTabItem tabItem1 ;
	
	public void createControl(final ViewPart part,final CTabFolder tab) {
		if(dtab==null){
			//deley create control
			dtab=new TextInsertTab(tab,SWT.NULL);
			dtab.setViewPart(part);
			tabItem1.setControl(dtab);
		}
	}
	
	public void createTab(ViewPart part, CTabFolder tab) {
		 tabItem1 = new CTabItem(tab, SWT.NONE);
		tabItem1.setText(Messages.getString("dropandsomething.textinsert"));
	
	
	}
	
	public class TextInsertTab extends DirectoryBasedDropSomething{ 
	public TextInsertTab(Composite parent, int style) {
		super(parent, style);
		
	}

	
	private Button ignore;
	private Button before;
	private Button after;
	private Button replace;
	private Text insertText;
	private Text targetText;
	private TextInsertSetting setting;
	private Label dragHere;

	
	private String[] extensions=new String[]{"htm","html","shtml","txt"};
	private CCombo charcode;
	
	private FileOverwriteControler overwriteControl;

	private Button keeptime;
	public Composite createControls(Composite parent) {
		log.trace("createControl");
		Composite composite=new Composite(parent,SWT.NULL);
		composite.setLayout(new GridLayout(1,true));
		
		
		
		Composite targetComposite=new Composite(composite,SWT.NULL);
		targetComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		targetComposite.setLayout(new GridLayout(3,false));
		Label label=new Label(targetComposite,SWT.NULL);
		label.setText(Messages.getString("textinsert.target"));
		
		ignore = new Button(targetComposite,SWT.CHECK);
		ignore.setSelection(true);//should change preference
		ignore.setText(Messages.getString("textinsert.ignore"));
		targetText = new Text(targetComposite,SWT.SINGLE);
		targetText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		
		targetText.setText("</body>");
		
		Composite beforeafter=new Composite(composite,SWT.NULL);
		beforeafter.setLayout(new GridLayout(3,true));
		before = new Button(beforeafter,SWT.RADIO);
		before.setSelection(true);//should change preference
		before.setText(Messages.getString("textinsert.before"));
		after = new Button(beforeafter,SWT.RADIO);
		after.setText(Messages.getString("textinsert.after"));
		replace = new Button(beforeafter,SWT.RADIO);
		replace.setText(Messages.getString("textinsert.replace"));
		
		
		
		createDirectoryInfo(composite);
	
		
		Label inserttextLabel=new Label(composite,SWT.NULL);
		inserttextLabel.setText(Messages.getString("textinsert.inserttext"));
		
		insertText = new Text(composite,SWT.MULTI);
		insertText.setLayoutData(new GridData(GridData.FILL_BOTH));
		insertText.setText("<!--put your code-->");
		
		Composite textandchar=new Composite(composite,SWT.NULL);
		textandchar.setLayout(new GridLayout(3,false));
		
		
		
		Label charcodelabel=new Label(textandchar,SWT.NULL);
		charcodelabel.setText(Messages.getString("textinsert.charcode"));
		
		charcode = new CCombo(textandchar,SWT.NULL);
		charcode.add("SJIS");//should support international
		charcode.add("iso-8859-1");
		
		charcode.add("MS932");
		charcode.add("EUC-JP");
		charcode.add("JIS");
		charcode.add("UTF-8");
		charcode.add("UTF-16");
		charcode.select(0);
		
		keeptime = new Button(textandchar,SWT.CHECK);
		keeptime.setText(Messages.getString("textinsert.keeptime"));
		dragHere = new Label(composite,SWT.NULL);
		//dragHere.setImage(PlatformUI.getWorkbench().getDisplay().getSystemImage(SWT.ICON_WARNING));
		
		GridData data=new GridData(GridData.FILL_BOTH);
		
		dragHere.setLayoutData(data);
		
		
		updateStatus();
		return composite;
	}
	
	
	
	public void setMessage(String text){
		if(dragHere!=null){//before initialize
		dragHere.setForeground(new Color(Display.getCurrent(),64,255,64));
		dragHere.setText(text);
		}
	}
	public void setErrorMessage(String text){
		if(dragHere!=null){
		dragHere.setForeground(new Color(null,255,0,0));
		dragHere.setText(text);
		}
	}
	
	public class FolderChoosed implements FileStatusChangeListener{

		public void removeList(FileStatusChangeEvent event) {
			// TODO Auto-generated method stub
			
		}

		public void addList(FileStatusChangeEvent event) {
			updateStatus();
		}
		
	}

	

	
	private void insertText(File input,File output){
		boolean equalsPath=input.equals(output);
		
		File tmpOutput=null;
		if(equalsPath){
			/*
			 * very important ,though read only file can delete ,i have to check this time.
			 */
			if(!output.canWrite()){
				log.info("read only file");
				printConsole(output,false);
				return;
			}
			log.info("same file:"+input);
			if(!setting.isBackup()){
				
				
				
				AskOverwrite ask=new AskOverwrite(overwriteControl,output);
				PlatformUI.getWorkbench().getDisplay().syncExec(ask);
				if(!ask.isOverwrite()){
				log.info("don't over write");
				return;
				}
			}
			try {
				log.info("make tmp");
				tmpOutput=File.createTempFile("tmpinsert",".html");
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}else{
			tmpOutput=output;
		}
		try {
			output.getParentFile().mkdirs();
			FileInputStream finput=new FileInputStream(input);
			TextInsertInputStream tinput=new TextInsertInputStream(finput,setting.getTargetText(),setting.getInsertText(),setting.getMode(),setting.getCharCode());
			BufferedInputStream binput=new BufferedInputStream(tinput);
			BufferedOutputStream boutput=new BufferedOutputStream(new FileOutputStream(tmpOutput));
			int b;
			while((b=binput.read())!=-1){
				boutput.write(b);
			}
			boutput.close();
			binput.close();
			
			if(setting.isBackup()){
				String outputPath=output.getAbsolutePath();
				File backupFile=new File(output.getParent(),output.getName()+".bkp");
				if(backupFile.exists()){
					boolean bk=backupFile.delete();
					if(!bk){
						log.info("delete faild:"+backupFile);
					}
				}
				boolean result=output.renameTo(backupFile);
				File newOutput=new File(outputPath);
				boolean result2=tmpOutput.renameTo(newOutput);
				if(setting.isKeeptime()){
				long time=output.lastModified();
				tmpOutput.setLastModified(time);
				}
				log.info("make backup:"+result+","+backupFile);
				log.info("make insert:"+result2+","+tmpOutput);
				if(!result2){
					tmpOutput.delete();
				}
				printConsole(newOutput,result2);
				
			}else{
				if(setting.isKeeptime()){
					long time=output.lastModified();
					tmpOutput.setLastModified(time);
					}
				
				boolean result2=output.delete();
				log.info("make insert:"+result2+","+output);
				
				boolean result=tmpOutput.renameTo(output);//replace.
				log.info("make insert:"+result+","+tmpOutput);
				
				if(!result){
					tmpOutput.delete();//don't need tmp file
				}
				
				printConsole(output,result);
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	public void printConsole(File file,boolean success){
		String message="";
		if(success){
			message="[success],"+file.getAbsolutePath()+"\n";
		}else{
			message="[faild],"+file.getAbsolutePath()+"\n";
		}
		Akj_betasPlugin.getDefault().getProcessPrinter().printOutput(message);
	}
	public void inconvert(File file) {
		if(setting.isSameFolder()){
		convert(file,file.getParent(),file.getParent());
		}else{
		convert(file,file.getParent(),setting.getExportDir());
		}
	}
	
	
	private void convert(File file,String baseDir,String exportDir){
		if(file.isFile()){
			if(PathnameUtils.isContainExtension(file.getName(),extensions)){
				String remain=PathnameUtils.getRemainPath(baseDir,file.getAbsolutePath());
				String newPath=PathnameUtils.createPath(exportDir+"\\",remain);
				insertText(file,new File(newPath));
				}else{
					StatusBarUtils.showStatusBar("not supported file "+file.getName());
				}
		}else{
			String[] lists=file.list();
			if(lists==null){
				return;
			}
			for (int i = 0; i < lists.length; i++) {
				convert(new File(file,lists[i]),baseDir,exportDir);
			}
		}
	}


	public class TextInsertSetting{
		private String insertText;
		private String targetText;
		private int mode;
		private boolean ignore;
		private boolean all;
		private String exportDir;
		private String charCode;
		private boolean backup;
		private int overwritemode;
		private boolean sameFolder;
		private boolean keeptime;
		public boolean isKeeptime() {
			return keeptime;
		}
		public void setKeeptime(boolean keeptime) {
			this.keeptime = keeptime;
		}
		public boolean isSameFolder() {
			return sameFolder;
		}
		public void setSameFolder(boolean sameFolder) {
			this.sameFolder = sameFolder;
		}
		public String getCharCode() {
			return charCode;
		}
		public void setCharCode(String charCode) {
			this.charCode = charCode;
		}
		public boolean isAll() {
			return all;
		}
		public void setAll(boolean all) {
			this.all = all;
		}
		public boolean isIgnore() {
			return ignore;
		}
		public void setIgnore(boolean ignore) {
			this.ignore = ignore;
		}
		public String getInsertText() {
			return insertText;
		}
		public void setInsertText(String insertText) {
			this.insertText = insertText;
		}
		public int getMode() {
			return mode;
		}
		public void setMode(int mode) {
			this.mode = mode;
		}
		public String getTargetText() {
			return targetText;
		}
		public void setTargetText(String targetText) {
			this.targetText = targetText;
		}
		public String getExportDir() {
			return exportDir;
		}
		public void setExportDir(String exportDir) {
			this.exportDir = exportDir;
		}
		public boolean isBackup() {
			return backup;
		}
		public void setBackup(boolean backup) {
			this.backup = backup;
		}
		public int getOverwritemode() {
			return overwritemode;
		}
		public void setOverwritemode(int overwritemode) {
			this.overwritemode = overwritemode;
		}
	}
	public void beforeConvert() {
		setting = new TextInsertSetting();
		setting.setIgnore(ignore.getSelection());
		setting.setInsertText(insertText.getText());
		int mode=0;
		if(after.getSelection()){
			mode=TextInsertInputStream.AFTER;
		}else if(replace.getSelection()){
			mode=TextInsertInputStream.REPLACE;
		}
		setting.setMode(mode);
		
		setting.setTargetText(targetText.getText());
		
		setting.setExportDir(directoryChooser.getAbsoluteFilePath());
		setting.setCharCode(charcode.getText());
		setting.setBackup(backup.getSelection());
		setting.setSameFolder(samefolder.getSelection());
		setting.setKeeptime(keeptime.getSelection());
	}


	public void afterConvert() {
		try {
			Thread.sleep(500);//for done.
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/* for initializing */
	public boolean setFocus(){
		/*
		IViewPart view=PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().findView(DropsomethingView.ID);
		log.info(view);
		IViewSite viewSite = view.getViewSite();
		IActionBars actionBars = viewSite.getActionBars();
		IStatusLineManager manager = actionBars.getStatusLineManager();
		manager.setErrorMessage("hello");
		*/
		return false;
	}
	
	public void updateStatus(){
		
		if(samefolder==null || directoryChooser==null){
			log.warn("you must createDirectoryInfo(composite); in createControls");
			return;
		}
		//choose export
		if(!samefolder.getSelection()&& directoryChooser.getAbsoluteFilePath().equals("")){
			setErrorMessage(Messages.getString("dropsomething.choose_folder"));
			setCanConvert(false);
		}
		//choose charset
		//drag and drop
		else {
			setMessage(Messages.getString("dropsomething.drag_folder"));
			setCanConvert(true);
		}
	}
	public void cancelConvert() {
		// TODO Auto-generated method stub
		
	}



	public IPreferenceStore getPreferenceStore(){
		return Akj_betasPlugin.getDefault().getPreferenceStore();
	}
	}
}